home *** CD-ROM | disk | FTP | other *** search
- /*
- C BASED FORTH-83 MULTI-TASKING KERNEL
-
- Copyright (C) 1988-1990 by Mikael R.K. Patel
-
- Computer Aided Design Laboratory (CADLAB)
- Department of Computer and Information Science
- Linkoping University
- S-581 83 LINKOPING
- SWEDEN
-
- Email: mip@ida.liu.se
-
- Started on: 30 June 1988
-
- Last updated on: 17 September 1990
-
- Dependencies:
- (cc) kernel.h, error.h, memory.h, io.c, compiler.v,
- locals.v, string.v, float.v, memory.v, queues.v,
- multi-tasking.v, exceptions.v
-
- Description:
- Virtual Forth machine and kernel code supporting multi-tasking of
- light weight processes. A pure 32-bit Forth-83 Standard implementation.
-
- Extended with floating point numbers, argument binding and local
- variables, exception handling, queue data management, multi-tasking,
- symbol hiding and casting, forwarding, null terminated string,
- memory allocation, file search paths, and source library module
- loading.
-
- Note:
- The kernel does not implement the block word set. All code is
- stored as text files.
-
- Copying:
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #include "kernel.h"
- #include "memory.h"
- #include "error.h"
- #include "io.h"
-
-
- /* EXTERNAL DECLARATIONS */
-
- extern VOID io_dispatch();
-
-
- /* INTERNAL FORWARD DECLARATIONS */
-
- extern code_entry qnumber;
- extern code_entry terminate;
- extern code_entry abort_entry;
- extern entry toexception;
- extern entry span;
- extern entry state;
- extern code_entry vocabulary;
-
-
- /* VOCABULARY LISTING PARAMETERS */
-
- #define COLUMNWIDTH 15
- #define LINEWIDTH 75
-
-
- /* CONTROL STRUCTURE MARKERS */
-
- #define ELSE 1
- #define THEN 2
- #define AGAIN 4
- #define UNTIL 8
- #define WHILE 16
- #define REPEAT 32
- #define LOOP 64
- #define PLUSLOOP 128
- #define OF 256
- #define ENDOF 512
- #define ENDCASE 1024
- #define SEMICOLON 2048
-
-
- /* MULTI-TASKING MACHINE REGISTERS */
-
- INT32 verbose; /* Application or programming mode */
- INT32 quited; /* Interpreter toploop state */
- INT32 running; /* Task switch flag */
- INT32 tasking; /* Multi-tasking flag */
-
- TASK tp; /* Task pointer */
- TASK foreground; /* Foreground task pointer */
-
-
- /* FORTH MACHINE REGISTERS */
-
- UNIV tos; /* Top of stack register */
- PTR sp; /* Parameter stack pointer */
- PTR s0; /* Bottom of parameter stack pointer */
-
- PTR32 ip; /* Instruction pointer */
- PTR32 rp; /* Return stack pointer */
- PTR32 r0; /* Bottom of return stack pointer */
-
- PTR32 fp; /* Argument frame pointer */
- PTR32 ep; /* Exception frame pointer */
-
-
- /* VOCABULARY SEARCH LISTS */
-
- #define CONTEXTSIZE 64
-
- static VOCABULARY_ENTRY current = &forth;
- static VOCABULARY_ENTRY context[CONTEXTSIZE] = {&forth};
-
-
- /* ENTRY LOOKUP CACHE, SIZE AND HASH FUNCTION */
-
- #define CACHESIZE 256
- #define hash(s) ((s[0] + (s[1] << 4)) & (CACHESIZE - 1))
-
- static ENTRY cache[CACHESIZE];
-
-
- /* DICTIONARY AREA FOR THREADED CODE AND DATA */
-
- PTR32 dictionary;
- PTR32 dp;
-
-
- /* INTERNAL STRUCTURE AND SIZES */
-
- static INT32 hld;
- static ENTRY thelast = NIL;
-
- #define PADSIZE 84
- static CHAR thepad[PADSIZE];
-
- #define TIBSIZE 256
- static CHAR thetib[TIBSIZE];
-
-
- /* CASTING IN INTERPRET TOP-LOOP */
-
- #define CASTING
-
-
- /* INNER MULTI-TASKING FORTH VIRTUAL MACHINE */
-
- VOID doinner()
- {
- INT32 e;
-
- /* Exception marking and handler */
- if (e = setjmp(restart)) {
- spush(e, INT32);
- doraise();
- }
-
- /* Run virtual machine until task switch */
- running = TRUE;
- while (running) {
-
- /* Fetch next thread to execute */
- register ENTRY p = (ENTRY) *ip++;
-
- /* Select on type of entry */
- switch (p -> code) {
- case CODE:
- ((SUBR) (p -> parameter))();
- break;
- case COLON:
- rpush(ip);
- fjump(p -> parameter);
- break;
- case VARIABLE:
- spush(&(p -> parameter), PTR32);
- break;
- case CONSTANT:
- spush(p -> parameter, INT32);
- break;
- case VOCABULARY:
- doappend((VOCABULARY_ENTRY) p);
- break;
- case CREATE:
- spush(p -> parameter, INT32);
- break;
- case USER:
- spush(((INT32) tp) + p -> parameter, INT32);
- break;
- case LOCAL:
- spush(*((PTR32) (INT32) fp - p -> parameter), INT32);
- break;
- case FORWARD:
- if (p -> parameter)
- docall((ENTRY) p -> parameter);
- else {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: unresolved forward entry\n", p -> name);
- doabort();
- }
- break;
- case EXCEPTION:
- spush(p, ENTRY);
- break;
- case FIELD:
- unary(p -> parameter +, INT32);
- break;
- default: /* DOES: FORTH LEVEL INTERPRETATION */
- rpush(ip);
- spush(p -> parameter, INT32);
- fjump(p -> code);
- break;
- }
- }
- }
-
- VOID docommand()
- {
- INT32 e;
-
- /* Exception marking and handler */
- if (e = setjmp(restart)) {
- spush(e, INT32);
- doraise();
- return;
- }
-
- /* Execute command on top of stack */
- doexecute();
-
- /* Check if this affects the virtual machine */
- if (rp != r0) {
- tasking = TRUE;
-
- /* Run the virtual machine and allow user extension */
- while (tasking) {
- doinner();
- io_dispatch();
- }
- }
- }
-
- VOID docall(p)
- ENTRY p;
- {
- /* Select on type of entry */
- switch (p -> code) {
- case CODE:
- ((SUBR) (p -> parameter))();
- return;
- case COLON:
- rpush(ip);
- fjump(p -> parameter);
- return;
- case VARIABLE:
- spush(&(p -> parameter), PTR32);
- return;
- case CONSTANT:
- spush(p -> parameter, INT32);
- return;
- case VOCABULARY:
- doappend((VOCABULARY_ENTRY) p);
- return;
- case CREATE:
- spush(p -> parameter, INT32);
- return;
- case USER:
- spush(((INT32) tp) + p -> parameter, INT32);
- return;
- case LOCAL:
- spush(*((PTR32) (INT32) fp - p -> parameter), INT32);
- return;
- case FORWARD:
- if (p -> parameter)
- docall((ENTRY) p -> parameter);
- else {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: unresolved forward entry\n", p -> name);
- doabort();
- }
- return;
- case EXCEPTION:
- spush(p, ENTRY);
- return;
- case FIELD:
- unary(p -> parameter +, INT32);
- return;
- default: /* DOES: FORTH LEVEL INTERPRETATION */
- rpush(ip);
- spush(p -> parameter, INT32);
- fjump(p -> code);
- return;
- }
- }
-
- VOID doappend(p)
- VOCABULARY_ENTRY p;
- {
- INT32 v;
-
- /* Flush the entry cache */
- spush(FALSE, BOOL);
- dorestore();
-
- /* Check if the vocabulary is a member of the current search set */
- for (v = 0; v < CONTEXTSIZE; v++)
-
- /* If a member then rotate the vocabulary first */
- if (p == context[v]) {
- for (; v; v--) context[v] = context[v - 1];
- context[0] = p;
- return;
- }
-
- /* If not a member, then insert first into the search set */
- for (v = CONTEXTSIZE - 1; v > 0; v--) context[v] = context[v - 1];
- context[0] = p;
- }
-
-
- /* VOCABULARY ROOT AND EXTERNAL VOCABULARIES */
-
- vocabulary_entry forth = {NIL, "forth", NORMAL, VOCABULARY, (ENTRY) &vocabulary, (ENTRY) &qnumber};
-
-
- /* COMPILER EXTENSIONS */
-
- #include "compiler.v"
-
- NORMAL_VOCABULARY(compiler, forth, "compiler", &backwardresolve, NIL);
-
-
- /* LOCAL VARIABLES AND ARGUMENT BINDING */
-
- #include "locals.v"
-
- NORMAL_VOCABULARY(locals, compiler, "locals", &curlebracket, NIL);
-
-
- /* NULL TERMINATED STRING */
-
- #include "string.v"
-
- NORMAL_VOCABULARY(string, locals, "string", &sprint, NIL);
-
-
- /* FLOATING POINT */
-
- #include "float.v"
-
- NORMAL_VOCABULARY(float_entry, string, "float", &qfloat, &qfloat);
-
-
- /* MEMORY MANAGEMENT */
-
- #include "memory.v"
-
- NORMAL_VOCABULARY(memory, float_entry, "memory", &free_entry, NIL);
-
-
- /* DOUBLE LINKED LISTS */
-
- #include "queues.v"
-
- NORMAL_VOCABULARY(queues, memory, "queues", &dequeue, NIL);
-
-
- /* MULTI-TASKING EXTENSIONS */
-
- #include "multi-tasking.v"
-
- NORMAL_VOCABULARY(multitasking, queues, "multi-tasking", &terminate, NIL);
-
-
- /* SIGNAL AND EXCEPTION MANAGEMENT */
-
- #include "exceptions.v"
-
- NORMAL_VOCABULARY(exceptions, multitasking, "exceptions", &raise, NIL);
-
-
- /* LOGIC: FORTH-83 VOCABULARY */
-
- NORMAL_CONSTANT(false, exceptions, "false", FALSE);
-
- NORMAL_CONSTANT(true, false, "true", TRUE);
-
- VOID doboolean()
- {
- compare(!= 0, INT32);
- }
-
- NORMAL_CODE(boolean, true, "boolean", doboolean);
-
- VOID donot()
- {
- unary(~, INT32);
- }
-
- NORMAL_CODE(not, boolean, "not", donot);
-
- VOID doand()
- {
- binary(&, INT32);
- }
-
- NORMAL_CODE(and, not, "and", doand);
-
- VOID door()
- {
- binary(|, INT32);
- }
-
- NORMAL_CODE(or, and, "or", door);
-
- VOID doxor()
- {
- binary(^, INT32);
- }
-
- NORMAL_CODE(xor, or, "xor", doxor);
-
- VOID doqwithin()
- {
- register INT32 value;
- register INT32 upper;
- register INT32 lower;
-
- upper = spop(INT32);
- lower = spop(INT32);
- value = spop(INT32);
-
- spush((value > upper) || (value < lower) ? FALSE : TRUE, BOOL);
- }
-
- NORMAL_CODE(qwithin, xor, "?within", doqwithin);
-
-
- /* STACK MANIPULATION */
-
- VOID dodepth()
- {
- register PTR32 t;
-
- t = (PTR32) sp;
- spush(((PTR32) s0 - t), INT32);
- }
-
- NORMAL_CODE(depth, qwithin, "depth", dodepth);
-
- VOID dodrop()
- {
- sdrop();
- }
-
- NORMAL_CODE(drop, depth, "drop", dodrop);
-
- VOID donip()
- {
- snip();
- }
-
- NORMAL_CODE(nip, drop, "nip", donip);
-
- VOID doswap()
- {
- sswap();
- }
-
- NORMAL_CODE(swap, nip, "swap", doswap);
-
- VOID dorot()
- {
- srot();
- }
-
- NORMAL_CODE(rot, swap, "rot", dorot);
-
- VOID dodashrot()
- {
- sdashrot();
- }
-
- NORMAL_CODE(dashrot, rot, "-rot", dodashrot);
-
- VOID doroll()
- {
- register UNIV e;
- register PTR s;
-
- /* Fetch roll parameters: number and element */
- e = snth(tos.INT32);
-
- /* Roll the stack */
- for (s = sp + tos.INT32; s > sp; s--) *s = *(s - 1);
- sp++;
-
- /* And assign the new top of stack */
- tos = e;
- }
-
- NORMAL_CODE(roll, dashrot, "roll", doroll);
-
- VOID doqdup()
- {
- if (tos.INT32) sdup();
- }
-
- NORMAL_CODE(qdup, roll, "?dup", doqdup);
-
- VOID dodup()
- {
- sdup();
- }
-
- NORMAL_CODE(dup_entry, qdup, "dup", dodup);
-
- VOID doover()
- {
- sover();
- }
-
- NORMAL_CODE(over, dup_entry, "over", doover);
-
- VOID dotuck()
- {
- stuck();
- }
-
- NORMAL_CODE(tuck, over, "tuck", dotuck);
-
- VOID dopick()
- {
- tos = snth(tos.INT32);
- }
-
- NORMAL_CODE(pick, tuck, "pick", dopick);
-
- VOID dotor()
- {
- rpush(spop(INT32));
- }
-
- COMPILATION_CODE(tor, pick, ">r", dotor);
-
- VOID dofromr()
- {
- spush(rpop(), INT32);
- }
-
- COMPILATION_CODE(fromr, tor, "r>", dofromr);
-
- VOID docopyr()
- {
- spush(*rp, INT32);
- }
-
- COMPILATION_CODE(copyr, fromr, "r@", docopyr);
-
- VOID dotwotor()
- {
- rpush(spop(INT32));
- rpush(spop(INT32));
- }
-
- COMPILATION_CODE(twotor, copyr, "2>r", dotwotor);
-
- VOID dotwofromr()
- {
- spush(rpop(), INT32);
- spush(rpop(), INT32);
- }
-
- COMPILATION_CODE(twofromr, twotor, "2r>", dotwofromr);
-
- VOID dotwodrop()
- {
- sndrop(1);
- }
-
- NORMAL_CODE(twodrop, twofromr, "2drop", dotwodrop);
-
- VOID dotwoswap()
- {
- register UNIV t;
-
- t = tos;
- tos = snth(1);
- snth(1) = t;
-
- t = snth(0);
- snth(0) = snth(2);
- snth(2) = t;
- }
-
- NORMAL_CODE(twoswap, twodrop, "2swap", dotwoswap);
-
- VOID dotworot()
- {
- register UNIV t;
-
- t = tos;
- tos = snth(3);
- snth(3) = snth(1);
- snth(1) = t;
-
- t = snth(0);
- snth(0) = snth(4);
- snth(4) = snth(2);
- snth(2) = t;
- }
-
- NORMAL_CODE(tworot, twoswap, "2rot", dotworot);
-
- VOID dotwodup()
- {
- spush(snth(1).INT32, INT32);
- spush(snth(1).INT32, INT32);
- }
-
- NORMAL_CODE(twodup, tworot, "2dup", dotwodup);
-
- VOID dotwoover()
- {
- spush(snth(3).INT32, INT32);
- spush(snth(3).INT32, INT32);
- }
-
- NORMAL_CODE(twoover, twodup, "2over", dotwoover);
-
-
- /* COMPARISON */
-
- VOID dolessthan()
- {
- relation(<, INT32);
- }
-
- NORMAL_CODE(lessthan, twoover, "<", dolessthan);
-
- VOID doequals()
- {
- relation(==, INT32);
- }
-
- NORMAL_CODE(equals, lessthan, "=", doequals);
-
- VOID dogreaterthan()
- {
- relation(>, INT32);
- }
-
- NORMAL_CODE(greaterthan, equals, ">", dogreaterthan);
-
- VOID dozeroless()
- {
- compare(< 0, INT32);
- }
-
- NORMAL_CODE(zeroless, greaterthan, "0<", dozeroless);
-
- VOID dozeroequals()
- {
- compare(== 0, INT32);
- }
-
- NORMAL_CODE(zeroequals, zeroless, "0=", dozeroequals);
-
- VOID dozerogreater()
- {
- compare(> 0, INT32);
- }
-
- NORMAL_CODE(zerogreater, zeroequals, "0>", dozerogreater);
-
- VOID doulessthan()
- {
- relation(<, NUM32);
- }
-
- NORMAL_CODE(ulessthan, zerogreater, "u<", doulessthan);
-
-
- /* CONSTANTS */
-
- NORMAL_CONSTANT(nil, ulessthan, "nil", NIL);
-
- NORMAL_CONSTANT(minusfour, nil, "-4", -4);
-
- NORMAL_CONSTANT(minustwo, minusfour, "-2", -2);
-
- NORMAL_CONSTANT(minusone, minustwo, "-1", -1);
-
- NORMAL_CONSTANT(zero, minusone, "0", 0);
-
- NORMAL_CONSTANT(one, zero, "1", 1);
-
- NORMAL_CONSTANT(two, one, "2", 2);
-
- NORMAL_CONSTANT(four, two, "4", 4);
-
-
- /* ARITHMETRIC */
-
- VOID doplus()
- {
- binary(+, INT32);
- }
-
- NORMAL_CODE(plus, four, "+", doplus);
-
- VOID dominus()
- {
- binary(-, INT32);
- }
-
- NORMAL_CODE(minus, plus, "-", dominus);
-
- VOID dooneplus()
- {
- unary(++, INT32);
- }
-
- NORMAL_CODE(oneplus, minus, "1+", dooneplus);
-
- VOID dooneminus()
- {
- unary(--, INT32);
- }
-
- NORMAL_CODE(oneminus, oneplus, "1-", dooneminus);
-
- VOID dotwoplus()
- {
- unary(2 +, INT32);
- }
-
- NORMAL_CODE(twoplus, oneminus, "2+", dotwoplus);
-
- VOID dotwominus()
- {
- unary(-2 +, INT32);
- }
-
- NORMAL_CODE(twominus, twoplus, "2-", dotwominus);
-
- VOID dotwotimes()
- {
- tos.INT32 <<= 1;
- }
-
- NORMAL_CODE(twotimes, twominus, "2*", dotwotimes);
-
- VOID doleftshift()
- {
- binary(<<, INT32);
- }
-
- NORMAL_CODE(leftshift, twotimes, "<<", doleftshift);
-
- VOID dotimes()
- {
- binary(*, INT32);
- }
-
- NORMAL_CODE(times_entry, leftshift, "*", dotimes);
-
- VOID doumtimes()
- {
- binary(*, NUM32);
- }
-
- NORMAL_CODE(utimes_entry, times_entry, "um*", doumtimes);
-
- VOID doumdividemod()
- {
- register NUM32 t;
-
- t = snth(0).NUM32;
- snth(0).NUM32 = t % tos.NUM32;
- tos.NUM32 = t / tos.NUM32;
- }
-
- NORMAL_CODE(umdividemod, utimes_entry, "um/mod", doumdividemod);
-
- VOID dotwodivide()
- {
- tos.INT32 >>= 1;
- }
-
- NORMAL_CODE(twodivide, umdividemod, "2/", dotwodivide);
-
- VOID dorightshift()
- {
- binary(>>, INT32);
- }
-
- NORMAL_CODE(rightshift, twodivide, ">>", dorightshift);
-
- VOID dodivide()
- {
- binary(/, INT32);
- }
-
- NORMAL_CODE(divide, rightshift, "/", dodivide);
-
- VOID domod()
- {
- binary(%, INT32);
- }
-
- NORMAL_CODE(mod, divide, "mod", domod);
-
- VOID dodividemod()
- {
- register INT32 t;
-
- t = snth(0).INT32;
- snth(0).INT32 = t % tos.INT32;
- tos.INT32 = t / tos.INT32;
- }
-
- NORMAL_CODE(dividemod, mod, "/mod", dodividemod);
-
- VOID dotimesdividemod()
- {
- register INT32 t;
-
- t = spop(INT32);
- tos.INT32 = tos.INT32 * snth(0).INT32;
- snth(0).INT32 = tos.INT32 % t;
- tos.INT32 = tos.INT32 / t;
- }
-
- NORMAL_CODE(timesdividemod, dividemod, "*/mod", dotimesdividemod);
-
- VOID dotimesdivide()
- {
- register INT32 t;
-
- t = spop(INT32);
- binary(*, INT32);
- spush(t, INT32);
- binary(/, INT32);
- }
-
- NORMAL_CODE(timesdivide, timesdividemod, "*/", dotimesdivide);
-
- VOID domin()
- {
- register INT32 t;
-
- t = spop(INT32);
- tos.INT32 = (t < tos.INT32 ? t : tos.INT32);
- }
-
- NORMAL_CODE(min, timesdivide, "min", domin);
-
- VOID domax()
- {
- register INT32 t;
-
- t = spop(INT32);
- tos.INT32 = (t > tos.INT32 ? t : tos.INT32);
- }
-
- NORMAL_CODE(max, min, "max", domax);
-
- VOID doabs()
- {
- tos.INT32 = (tos.INT32 < 0 ? - tos.INT32 : tos.INT32);
- }
-
- NORMAL_CODE(abs_entry, max, "abs", doabs);
-
- VOID donegate()
- {
- unary(-, INT32);
- }
-
- NORMAL_CODE(negate, abs_entry, "negate", donegate);
-
-
- /* MEMORY */
-
- VOID dofetch()
- {
- unary(*(PTR32), INT32);
- }
-
- NORMAL_CODE(fetch, negate, "@", dofetch);
-
- VOID dostore()
- {
- register PTR32 t;
-
- t = spop(PTR32);
- *t = spop(INT32);
- }
-
- NORMAL_CODE(store, fetch, "!", dostore);
-
- VOID dowfetch()
- {
- unary(*(NUM16 *), NUM32);
- }
-
- NORMAL_CODE(wfetch, store, "w@", dowfetch);
-
- VOID dolesswfetch()
- {
- unary(*(PTR16), INT32);
- }
-
- NORMAL_CODE(lesswfetch, wfetch, "<w@", dolesswfetch);
-
- VOID dowstore()
- {
- register PTR16 t;
-
- t = spop(PTR16);
- *t = spop(INT32);
- }
-
- NORMAL_CODE(wstore, lesswfetch, "w!", dowstore);
-
- VOID docfetch()
- {
- unary(*(NUM8 *), NUM32);
- }
-
- NORMAL_CODE(cfetch, wstore, "c@", docfetch);
-
- VOID dolesscfetch()
- {
- unary(*(PTR8), INT32);
- }
-
- NORMAL_CODE(lesscfetch, cfetch, "<c@", dolesscfetch);
-
- VOID docstore()
- {
- register PTR8 t;
-
- t = spop(PTR8);
- *t = spop(INT32);
- }
-
- NORMAL_CODE(cstore, lesscfetch, "c!", docstore);
-
- VOID doffetch()
- {
- register INT32 pos;
- register INT32 width;
-
- width = spop(INT32);
- pos = spop(INT32);
- if (width < sizeof(INT32) * 8)
- tos.INT32 = (tos.INT32 >> pos) & ~(-1 << width);
- }
-
- NORMAL_CODE(ffetch, cstore, "f@", doffetch);
-
- VOID dolessffetch()
- {
- register INT32 pos;
- register INT32 width;
-
- width = spop(INT32);
- pos = spop(INT32);
- if (width < sizeof(INT32) * 8) {
- tos.INT32 = (tos.INT32 >> pos) & ~(-1 << width);
- if ((1 << (width - 1)) & tos.INT32) {
- tos.INT32 = (tos.INT32) | (-1 << width);
- }
- }
- }
-
- NORMAL_CODE(lessffetch, ffetch, "<f@", dolessffetch);
-
- VOID dofstore()
- {
- register INT32 pos;
- register INT32 width;
- register INT32 value;
-
- width = spop(INT32);
- pos = spop(INT32);
- value = spop(INT32);
- tos.INT32 = ((tos.INT32 & ~(-1 << width)) << pos) | (value & ~((~(-1 << width)) << pos));
- }
-
- NORMAL_CODE(fstore, lessffetch, "f!", dofstore);
-
- VOID dobfetch()
- {
- register INT32 bit;
-
- bit = spop(INT32);
- tos.INT32 = (((tos.INT32 >> bit) & 1) ? TRUE : FALSE);
- }
-
- NORMAL_CODE(bfetch, fstore, "b@", dobfetch);
-
- VOID dobstore()
- {
- register INT32 bit;
- register INT32 value;
-
- bit = spop(INT32);
- value = spop(INT32);
- tos.INT32 = (tos.INT32 ? (value | (1 << bit)) : (value & ~(1 << bit)));
- }
-
- NORMAL_CODE(bstore, bfetch, "b!", dobstore);
-
- VOID doplusstore()
- {
- register PTR32 t;
-
- t = spop(PTR32);
- *t += spop(INT32);
- }
-
- NORMAL_CODE(plusstore, bstore, "+!", doplusstore);
-
- VOID dotwofetch()
- {
- register PTR32 t;
-
- t = tos.PTR32;
- spush(*t++, INT32);
- snth(0).INT32 = *t;
- }
-
- NORMAL_CODE(twofetch, plusstore, "2@", dotwofetch);
-
- VOID dotwostore()
- {
- register PTR32 t;
-
- t = spop(PTR32);
- *t++ = spop(INT32);
- *t = spop(INT32);
- }
-
- NORMAL_CODE(twostore, twofetch, "2!", dotwostore);
-
-
- /* STRINGS */
-
- VOID docmove()
- {
- register INT32 n;
- register CSTR to;
- register CSTR from;
-
- n = spop(INT32);
- to = spop(CSTR);
- from = spop(CSTR);
-
- while (--n != -1) *to++ = *from++;
- }
-
- NORMAL_CODE(cmove, twostore, "cmove", docmove);
-
- VOID docmoveup()
- {
- register INT32 n;
- register CSTR to;
- register CSTR from;
-
- n = spop(INT32);
- to = spop(CSTR);
- from = spop(CSTR);
-
- to += n;
- from += n;
- while (--n != -1) *--to = *--from;
- }
-
- NORMAL_CODE(cmoveup, cmove, "cmove>", docmoveup);
-
- VOID dofill()
- {
- register INT32 with;
- register INT32 n;
- register CSTR from;
-
- with = spop(INT32);
- n = spop(INT32);
- from = spop(CSTR);
-
- while (--n != -1) *from++ = with;
- }
-
- NORMAL_CODE(fill, cmoveup, "fill", dofill);
-
- VOID docount()
- {
- register CSTR t;
-
- t = spop(CSTR);
- spush(*t++, INT32);
- spush(t, CSTR);
- }
-
- NORMAL_CODE(count, fill, "count", docount);
-
- VOID dobounds()
- {
- register CSTR n;
-
- n = snth(0).CSTR;
- snth(0).CSTR = snth(0).CSTR + tos.INT32;
- tos.CSTR = n;
- }
-
- NORMAL_CODE(bounds, count, "bounds", dobounds);
-
- VOID dodashtrailing()
- {
- register CSTR p;
-
- p = snth(0).CSTR + tos.INT32;
- tos.INT32 += 1;
- while (--tos.INT32 && (*--p == ' '));
- }
-
- NORMAL_CODE(dashtrailing, bounds, "-trailing", dodashtrailing);
-
- VOID dodashmatch()
- {
- register INT32 n;
- register CSTR s;
- register CSTR t;
-
- n = spop(INT32);
- s = spop(CSTR);
- t = spop(CSTR);
-
- if (n) {
- while ((n) && (*s++ == *t++)) n--;
- spush(n ? TRUE : FALSE, BOOL);
- }
- else {
- spush(TRUE, BOOL);
- }
- }
-
- NORMAL_CODE(dashmatch, dashtrailing, "-match", dodashmatch);
-
-
- /* NUMERICAL CONVERSION */
-
- NORMAL_VARIABLE(base, dashmatch, "base", 10);
-
- VOID dobinary()
- {
- base.parameter = 2;
- }
-
- NORMAL_CODE(binary_entry, base, "binary", dobinary);
-
- VOID dooctal()
- {
- base.parameter = 8;
- }
-
- NORMAL_CODE(octal, binary_entry, "octal", dooctal);
-
- VOID dodecimal()
- {
- base.parameter = 10;
- }
-
- NORMAL_CODE(decimal, octal, "decimal", dodecimal);
-
- VOID dohex()
- {
- base.parameter = 16;
- }
-
- NORMAL_CODE(hex, decimal, "hex", dohex);
-
- VOID doconvert()
- {
- register CHAR c;
- register INT32 b;
- register INT32 n;
-
- b = base.parameter;
- n = snth(0).INT32;
-
- for (;;) {
- c = *tos.CSTR;
- if (c < '0' || c > 'z' || (c > '9' && c < 'a')) {
- snth(0).INT32 = n;
- return;
- }
- else {
- if (c > '9') c = c - 'a' + ':';
- c = c - '0';
- if (c < 0 || c >= b) {
- snth(0).INT32 = n;
- return;
- }
- n = (n * b) + c;
- tos.INT32 += 1;
- }
- }
- }
-
- NORMAL_CODE(convert, hex, "convert", doconvert);
-
- VOID dolesssharp()
- {
- hld = (INT32) thepad + PADSIZE;
- }
-
- NORMAL_CODE(lesssharp, convert, "<#", dolesssharp);
-
- VOID dosharp()
- {
- register NUM32 n;
-
- n = tos.NUM32;
- tos.NUM32 = n / (NUM32) base.parameter;
- n = n % (NUM32) base.parameter;
- *(CSTR) --hld = n + ((n > 9) ? 'a' - 10 : '0');
- }
-
- NORMAL_CODE(sharp, lesssharp, "#", dosharp);
-
- VOID dosharps()
- {
- do { dosharp(); } while (tos.INT32);
- }
-
- NORMAL_CODE(sharps, sharp, "#s", dosharps);
-
- VOID dohold()
- {
- *(CSTR) --hld = spop(INT32);
- }
-
- NORMAL_CODE(hold, sharps, "hold", dohold);
-
- VOID dosign()
- {
- INT32 flag;
-
- flag = spop(INT32);
- if (flag < 0) *(CSTR) --hld = '-';
- }
-
- NORMAL_CODE(sign, hold, "sign", dosign);
-
- VOID dosharpgreater()
- {
- tos.INT32 = hld;
- spush((INT32) thepad + PADSIZE - hld, INT32);
- }
-
- NORMAL_CODE(sharpgreater, sign, "#>", dosharpgreater);
-
- VOID doqnumber()
- {
- register CSTR s0;
- register CSTR s1;
-
- s0 = spop(CSTR);
- spush(0, INT32);
- if (*s0 == '-') {
- spush(s0 + 1, CSTR);
- }
- else {
- spush(s0, CSTR);
- }
- doconvert();
- s1 = spop(CSTR);
- if (*s1 == '\0') {
- if (*s0 == '-') unary(-, INT32);
- spush(TRUE, BOOL);
- }
- else {
- tos.CSTR = s0;
- spush(FALSE, BOOL);
- }
- }
-
- NORMAL_CODE(qnumber, sharpgreater, "?number", doqnumber);
-
-
- /* CONTROL STRUCTURES */
-
- INT32 docheck(this)
- INT this;
- {
- ENTRY last;
- INT32 follow = spop(INT32);
-
- /* Check if the symbol is in the follow set */
- if (this & follow) {
-
- /* Return true is so */
- return TRUE;
- }
- else {
-
- /* Else report a control structure error */
- dolast();
- last = spop(ENTRY);
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: illegal control structure\n", last -> name);
- doabort();
-
- return FALSE;
- }
- }
-
- VOID dodo()
- {
- spush(&parendo, CODE_ENTRY);
- dothread();
- doforwardmark();
- dobackwardmark();
- spush(LOOP+PLUSLOOP, INT32);
- }
-
- COMPILATION_IMMEDIATE_CODE(do_entry, qnumber, "do", dodo);
-
- VOID doqdo()
- {
- spush(&parenqdo, CODE_ENTRY);
- dothread();
- doforwardmark();
- dobackwardmark();
- spush(LOOP+PLUSLOOP, INT32);
- }
-
- COMPILATION_IMMEDIATE_CODE(qdo_entry, do_entry, "?do", doqdo);
-
- VOID doloop()
- {
- if (docheck(LOOP)) {
- spush(&parenloop, CODE_ENTRY);
- dothread();
- dobackwardresolve();
- doforwardresolve();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(loop, qdo_entry, "loop", doloop);
-
- VOID doplusloop()
- {
- if (docheck(PLUSLOOP)) {
- spush(&parenplusloop, CODE_ENTRY);
- dothread();
- dobackwardresolve();
- doforwardresolve();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(plusloop, loop, "+loop", doplusloop);
-
- VOID doleave()
- {
- rndrop(2);
- fjump(rpop());
- fbranch(*ip);
- }
-
- COMPILATION_CODE(leave, plusloop, "leave", doleave);
-
- VOID doi()
- {
- spush(rnth(1), INT32);
- }
-
- COMPILATION_CODE(i_entry, leave,"i", doi);
-
- VOID doj()
- {
- spush(rnth(4), INT32);
- }
-
- COMPILATION_CODE(j_entry, i_entry, "j", doj);
-
- VOID doif()
- {
- spush(&parenqbranch, CODE_ENTRY);
- dothread();
- doforwardmark();
- spush(ELSE+THEN, INT32);
- }
-
- COMPILATION_IMMEDIATE_CODE(if_entry, j_entry, "if", doif);
-
- VOID doelse()
- {
- if (docheck(ELSE)) {
- spush(&parenbranch, CODE_ENTRY);
- dothread();
- doforwardmark();
- doswap();
- doforwardresolve();
- spush(THEN, INT32);
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(else_entry, if_entry, "else", doelse);
-
- VOID dothen()
- {
- if (docheck(THEN)) {
- doforwardresolve();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(then_entry, else_entry, "then", dothen);
-
- VOID docase()
- {
- spush(0, INT32);
- spush(OF+ENDCASE, INT32);
- }
-
- COMPILATION_IMMEDIATE_CODE(case_entry, then_entry, "case", docase);
-
- VOID doof()
- {
- if (docheck(OF)) {
- spush(&over, CODE_ENTRY);
- dothread();
- spush(&equals, CODE_ENTRY);
- dothread();
- spush(&parenqbranch, CODE_ENTRY);
- dothread();
- doforwardmark();
- spush(&drop, CODE_ENTRY);
- dothread();
- spush(ENDOF, INT32);
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(of_entry, case_entry, "of", doof);
-
- VOID doendof()
- {
- if (docheck(ENDOF)) {
- spush(&parenbranch, CODE_ENTRY);
- dothread();
- doforwardmark();
- doswap();
- doforwardresolve();
- spush(OF+ENDCASE, INT32);
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(endof, of_entry, "endof", doendof);
-
- VOID doendcase()
- {
- if (docheck(ENDCASE)) {
- spush(&drop, CODE_ENTRY);
- dothread();
- while (tos.INT32) doforwardresolve();
- dodrop();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(endcase, endof, "endcase", doendcase);
-
- VOID dobegin()
- {
- dobackwardmark();
- spush(AGAIN+UNTIL+WHILE, INT32);
- }
-
- COMPILATION_IMMEDIATE_CODE(begin, endcase, "begin", dobegin);
-
- VOID dountil()
- {
- if (docheck(UNTIL)) {
- spush(&parenqbranch, CODE_ENTRY);
- dothread();
- dobackwardresolve();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(until, begin, "until", dountil);
-
- VOID dowhile()
- {
- if (docheck(WHILE)) {
- spush(&parenqbranch, CODE_ENTRY);
- dothread();
- doforwardmark();
- spush(REPEAT, INT32);
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(while_entry, until, "while", dowhile);
-
- VOID dorepeat()
- {
- if (docheck(REPEAT)) {
- spush(&parenbranch, CODE_ENTRY);
- dothread();
- doswap();
- dobackwardresolve();
- doforwardresolve();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(repeat, while_entry, "repeat", dorepeat);
-
- VOID doagain()
- {
- if (docheck(AGAIN)) {
- spush(&parenbranch, CODE_ENTRY);
- dothread();
- dobackwardresolve();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(again, repeat, "again", doagain);
-
- VOID dorecurse()
- {
- dolast();
- dothread();
- }
-
- COMPILATION_IMMEDIATE_CODE(recurse, again, "recurse", dorecurse);
-
- VOID dotailrecurse()
- {
- if (theframed) {
- spush(&parenunlink, CODE_ENTRY);
- dothread();
- }
- dolast();
- dotobody();
- spush(&parenbranch, CODE_ENTRY);
- dothread();
- dobackwardresolve();
- }
-
- COMPILATION_IMMEDIATE_CODE(tailrecurse, recurse, "tail-recurse", dotailrecurse);
-
- VOID doexit()
- {
- fsemicolon();
- }
-
- COMPILATION_CODE(exit_entry, tailrecurse, "exit", doexit);
-
- VOID doexecute()
- {
- ENTRY t;
-
- t = spop(ENTRY);
- docall(t);
- }
-
- NORMAL_CODE(execute, exit_entry, "execute", doexecute);
-
- VOID dobye()
- {
- quited = FALSE;
- }
-
- NORMAL_CODE(bye, execute, "bye", dobye);
-
-
- /* TERMINAL INPUT-OUTPUT */
-
- VOID dodot()
- {
- if (tos.INT32 < 0) {
- (VOID) fputc('-', io_outf);
- unary(-, INT32);
- }
- doudot();
- }
-
- NORMAL_CODE(dot, bye, ".", dodot);
-
- VOID dodotr()
- {
- INT32 s, t;
-
- t = spop(INT32);
- s = tos.INT32;
- doabs();
- dolesssharp();
- dosharps();
- spush(s, INT32);
- dosign();
- dosharpgreater();
- spush(t, INT32);
- sover();
- dominus();
- dospaces();
- dotype();
- }
-
- NORMAL_CODE(dotr, dot, ".r", dodotr);
-
- VOID doudot()
- {
- dolesssharp();
- dosharps();
- dosharpgreater();
- dotype();
- dospace();
- }
-
- NORMAL_CODE(udot, dotr, "u.", doudot);
-
- VOID doudotr()
- {
- INT32 t;
-
- t = spop(INT32);
- dolesssharp();
- dosharps();
- dosharpgreater();
- spush(t, INT32);
- sover();
- dominus();
- dospaces();
- dotype();
- }
-
- NORMAL_CODE(udotr, udot, "u.r", doudotr);
-
- VOID doascii()
- {
- spush(' ', INT32);
- doword();
- docfetch();
- doliteral();
- }
-
- IMMEDIATE_CODE(ascii, udotr, "ascii", doascii);
-
- VOID dodotquote()
- {
- (VOID) io_scan(thetib, '"');
- spush(thetib, CSTR);
- dosdup();
- snip();
- spush(&parendotquote, CODE_ENTRY);
- dothread();
- docomma();
- }
-
- COMPILATION_IMMEDIATE_CODE(dotquote, ascii, ".\"", dodotquote);
-
- VOID dodotparen()
- {
- (VOID) io_scan(thetib, ')');
- spush(thetib, CSTR);
- dosprint();
- }
-
- IMMEDIATE_CODE(dotparen, dotquote, ".(", dodotparen);
-
- VOID dodots()
- {
- register PTR s;
-
- /* Print the stack depth */
- (VOID) fprintf(io_outf, "[%d] ", s0 - sp);
-
- /* Check if there are any elements on the stack */
- if (s0 - sp > 0) {
-
- /* Print them and don't forget top of stack */
- for (s = s0 - 2; s >= sp; s--) {
- (VOID) fprintf(io_outf, "\\");
- spush(s -> INT32, INT32);
- if (tos.INT32 < 0) {
- (VOID) fputc('-', io_outf);
- unary(-, INT32);
- }
- dolesssharp();
- dosharps();
- dosharpgreater();
- dotype();
- }
- (VOID) fprintf(io_outf, "\\");
- dodup();
- dodot();
- }
- }
-
- NORMAL_CODE(dots, dotparen, ".s", dodots);
-
- VOID docr()
- {
- (VOID) fputc('\n', io_outf);
- }
-
- NORMAL_CODE(cr, dots, "cr", docr);
-
- VOID doemit()
- {
- CHAR c;
-
- c = (CHAR) spop(INT32);
- (VOID) fputc(c, io_outf);
- }
-
- NORMAL_CODE(emit, cr, "emit", doemit);
-
- VOID dotype()
- {
- register INT32 n;
- register CSTR s;
-
- n = spop(INT32);
- s = spop(CSTR);
- while (n--) (VOID) fputc(*s++, io_outf);
- }
-
- NORMAL_CODE(type, emit, "type", dotype);
-
- VOID dospace()
- {
- (VOID) fputc(' ', io_outf);
- }
-
- NORMAL_CODE(space, type, "space", dospace);
-
- VOID dospaces()
- {
- register INT32 n;
-
- n = spop(INT32);
- while (n-- > 0) (VOID) fputc(' ', io_outf);
- }
-
- NORMAL_CODE(spaces, space, "spaces", dospaces);
-
- VOID dokey()
- {
- spush(io_getchar(), INT32);
- }
-
- NORMAL_CODE(key, spaces, "key", dokey);
-
- VOID doexpect()
- {
- register CHAR c;
- register CSTR s0;
- register CSTR s1;
- register INT32 n;
-
- /* Pop buffer pointer and size */
- n = spop(INT32);
- s0 = s1 = spop(CSTR);
-
- /* Fill buffer until end of line or buffer */
- while (io_not_eof() && (n-- > 0) && ((c = io_getchar()) != '\n')) *s1++ = c;
-
- io_newline();
-
- /* Set span to number of characters received */
- span.parameter = (INT32) (s1 - s0);
- }
-
- NORMAL_CODE(expect, key, "expect", doexpect);
-
- NORMAL_VARIABLE(span, expect, "span", 0);
-
- VOID doline()
- {
- spush(io_line(), INT32);
- }
-
- NORMAL_CODE(line, span, "line", doline);
-
- VOID dosource()
- {
- spush(io_source(), CSTR);
- }
-
- NORMAL_CODE(source, line, "source", dosource);
-
-
- /* PROGRAM BEGINNING AND TERMINATION */
-
- VOID doforth83()
- {
-
- }
-
- NORMAL_CODE(forth83, source, "forth-83", doforth83);
-
- VOID dointerpret()
- {
- INT32 flag; /* Flag value returned by for words */
-
- #ifdef CASTING
- INT32 cast; /* Casting operation flag */
- #endif
-
- quited = TRUE; /* Iterate until bye or end of input */
-
- while (quited) {
-
- /* Check stack underflow */
- if (s0 < sp) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "interpret: stack underflow\n");
- doabort();
- }
-
- /* Scan for the next symbol */
- spush(' ', INT32);
- doword();
-
- /* Exit top loop if end of input stream */
- if (io_eof()) {
- sdrop();
- return;
- }
-
- /* Search for the symbol in the current vocabulary search set*/
- dofind();
- flag = spop(INT32);
-
- #ifdef CASTING
- /* Check for vocabulary casting prefix */
- for (cast = flag; !cast;) {
- CSTR s = tos.CSTR;
- INT32 l = strlen(s) - 1;
-
- /* Assume casting prefix */
- cast = TRUE;
-
- /* Check casting syntax, vocabulary name within parethesis */
- if ((s[0] == '(') && (s[l] == ')')) {
-
- /* Remove the parenthesis from the input string */
- s[l] = 0;
- unary(++, INT32);
-
- /* Search for the symbol again */
- dofind();
- flag = spop(INT32);
-
- /* If found check that its a vocabulary */
- if (flag) {
- ENTRY v = spop(ENTRY);
-
- /* Check that the symbol is really a vocabulary */
- if (v -> code == VOCABULARY) {
-
- /* Scan for a new symbol */
- spush(' ', INT32);
- doword();
-
- /* Exit top loop if end of input stream */
- if (io_eof()) {
- sdrop();
- return;
- }
-
- /* And look for it in the given vocabulary */
- spush(v, ENTRY);
- dolookup();
- flag = spop(INT32);
- cast = flag;
- }
- }
- else {
- /* Restore string after vocabulary name test */
- s[l] = ')';
- unary(--, INT32);
- }
- }
- }
- #endif
-
- /* If found then execute or thread the symbol */
- if (flag) {
- if (state.parameter == flag)
- dothread();
- else
- docommand();
- }
- else {
- /* Else check if it is a literal */
- dorecognize();
- flag = spop(INT32);
- if (flag) {
- doliteral();
- }
- else {
- /* Print source file and line number */
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
-
- /* If not print error message and abort */
- (VOID) fprintf(io_errf, "%s ??\n", tos.CSTR);
- doabort();
- }
- }
- }
- quited = TRUE;
- }
-
- NORMAL_CODE(interpret, forth83, "interpret", dointerpret);
-
- VOID doquit()
- {
- rinit();
- doleftbracket();
- dointerpret();
- }
-
- NORMAL_CODE(quit, interpret, "quit", doquit);
-
- VOID doabort()
- {
- /* Check if it is the foreground task */
- if (tp == foreground) {
- sinit();
- doleftbracket();
- io_flush();
- }
-
- /* Terminate aborted tasks */
- doterminate();
- }
-
- NORMAL_CODE(abort_entry, quit, "abort", doabort);
-
- VOID doabortquote()
- {
- spush('"', INT32);
- doword();
- dosdup();
- snip();
- spush(&parenabortquote, CODE_ENTRY);
- dothread();
- docomma();
- }
-
- COMPILATION_IMMEDIATE_CODE(abortquote, abort_entry, "abort\"", doabortquote);
-
-
- /* DICTIONARY ADDRESSES */
-
- VOID dohere()
- {
- spush(dp, PTR32);
- }
-
- NORMAL_CODE(here, abortquote, "here", dohere);
-
- NORMAL_CONSTANT(pad, here, "pad", (INT32) thepad);
-
- NORMAL_CONSTANT(tib, pad, "tib", (INT32) thetib);
-
- VOID dotobody()
- {
- tos.INT32 = tos.ENTRY -> parameter;
- }
-
- NORMAL_CODE(tobody, tib, ">body", dotobody);
-
- VOID dodotname()
- {
- ENTRY e = spop(ENTRY);
-
- (VOID) fprintf(io_outf, "%s", e -> name);
- }
-
- NORMAL_CODE(dotname, tobody, ".name", dodotname);
-
- NORMAL_CONSTANT(cell, dotname, "cell", 4);
-
- VOID docells()
- {
- tos.INT32 <<= 2;
- }
-
- NORMAL_CODE(cells, cell, "cells", docells);
-
- VOID docellplus()
- {
- tos.INT32 += 4;
- }
-
- NORMAL_CODE(cellplus, cells, "cell+", docellplus);
-
-
- /* COMPILER AND INTERPRETER WORDS */
-
- VOID dosharpif()
- {
- INT32 symbol;
- BOOL flag;
-
- flag = spop(BOOL);
-
- if (!flag) {
- do {
- spush(' ', INT32);
- doword();
- symbol = spop(INT32);
- if (STREQ(symbol, "#if")) {
- dosharpelse();
- spush(' ', INT32);
- doword();
- symbol = spop(INT32);
- }
- } while (!((STREQ(symbol, "#else") || STREQ(symbol, "#then"))));
- }
- }
-
- IMMEDIATE_CODE(sharpif, cellplus, "#if", dosharpif);
-
- VOID dosharpelse()
- {
- INT32 symbol;
-
- do {
- spush(' ', INT32);
- doword();
- symbol = spop(INT32);
- if (STREQ(symbol, "#if")) {
- dosharpelse();
- spush(' ', INT32);
- doword();
- symbol = spop(INT32);
- }
- } while (!STREQ(symbol, "#then"));
- }
-
- IMMEDIATE_CODE(sharpelse, sharpif, "#else", dosharpelse);
-
- VOID dosharpthen()
- {
-
- }
-
- IMMEDIATE_CODE(sharpthen, sharpelse, "#then", dosharpthen);
-
- VOID dosharpifdef()
- {
- spush(' ', INT32);
- doword();
- dofind();
- doswap();
- dodrop();
- dosharpif();
- }
-
- IMMEDIATE_CODE(sharpifdef, sharpthen, "#ifdef", dosharpifdef);
-
- VOID dosharpifundef()
- {
- spush(' ', INT32);
- doword();
- dofind();
- doswap();
- dodrop();
- dozeroequals();
- dosharpif();
- }
-
- IMMEDIATE_CODE(sharpifundef, sharpifdef, "#ifundef", dosharpifundef);
-
- VOID dosharpinclude()
- {
- INT32 flag;
- CSTR fname;
-
- spush(' ', INT32);
- doword();
- fname = spop(CSTR);
- if (flag = io_infile(fname) == IO_UNKNOWN_FILE) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: file not found\n", fname);
- }
- else {
- if (flag == IO_TOO_MANY_FILES) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: too many files open\n", fname);
- }
- }
- }
-
- NORMAL_CODE(sharpinclude, sharpifundef, "#include", dosharpinclude);
-
- VOID dosharppath()
- {
- INT32 flag;
-
- spush(' ', INT32);
- doword();
- if (flag = io_path(tos.CSTR, IO_PATH_FIRST) == IO_UNKNOWN_PATH) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: unknown environment variable\n", tos.CSTR);
- }
- else {
- if (flag == IO_TOO_MANY_PATHS) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: too many paths defined\n", tos.CSTR);
- }
- }
- dodrop();
- }
-
- NORMAL_CODE(sharppath, sharpinclude, "#path", dosharppath);
-
- VOID doparen()
- {
- CHAR c;
-
- while (c = io_getchar())
- if (io_eof()) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "kernel: end of file during comment\n");
- return;
- }
- else
- if (c == ')') return;
- else
- if (c == '(') {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "kernel: warning balanced comment\n");
- doparen();
- }
- }
-
- IMMEDIATE_CODE(paren, sharppath, "(", doparen);
-
- VOID dobackslash()
- {
- io_skip('\n');
- }
-
- IMMEDIATE_CODE(backslash, paren, "\\", dobackslash);
-
- VOID docomma()
- {
- *dp++ = spop(INT32);
- }
-
- NORMAL_CODE(comma, backslash, ",", docomma);
-
- VOID doallot()
- {
- INT32 n;
-
- n = spop(INT32);
- dp = (PTR32) ((PTR8) dp + n);
- }
-
- NORMAL_CODE(allot, comma, "allot", doallot);
-
- VOID doalign()
- {
- align(dp);
- }
-
- NORMAL_CODE(align_entry, allot, "align", doalign);
-
- VOID dodoes()
- {
- if (theframed != NIL) {
- spush(&parenunlinkdoes, CODE_ENTRY);
- }
- else {
- spush(&parendoes, CODE_ENTRY);
- }
- dothread();
- doremovelocals();
- }
-
- COMPILATION_IMMEDIATE_CODE(does, align_entry, "does>", dodoes);
-
- VOID doimmediate()
- {
- current -> last -> mode |= IMMEDIATE;
- }
-
- NORMAL_CODE(immediate, does, "immediate", doimmediate);
-
- VOID doexecution()
- {
- current -> last -> mode |= EXECUTION;
- }
-
- NORMAL_CODE(execution, immediate, "execution", doexecution);
-
- VOID docompilation()
- {
- current -> last -> mode |= COMPILATION;
- }
-
- NORMAL_CODE(compilation, execution, "compilation", docompilation);
-
- VOID doprivate()
- {
- current -> last -> mode |= PRIVATE;
- }
-
- NORMAL_CODE(private_entry, compilation, "private", doprivate);
-
- VOID dorecognizer()
- {
- current -> recognizer = current -> last;
- }
-
- NORMAL_CODE(recognizer, private_entry, "recognizer", dorecognizer);
-
- VOID dobracketcompile()
- {
- dotick();
- dothread();
- }
-
- COMPILATION_IMMEDIATE_CODE(bracketcompile, recognizer, "[compile]", dobracketcompile);
-
- VOID docompile()
- {
- spush(*ip++, INT32);
- dothread();
- }
-
- COMPILATION_CODE(compile, bracketcompile, "compile", docompile);
-
- VOID doqcompile()
- {
- if (state.parameter) docompile();
- }
-
- COMPILATION_CODE(qcompile, compile, "?compile", doqcompile);
-
- NORMAL_VARIABLE(state, qcompile, "state", FALSE);
-
- VOID docompiling()
- {
- spush(state.parameter, INT32);
- }
-
- NORMAL_CODE(compiling, state, "compiling", docompiling);
-
- VOID doliteral()
- {
- if (state.parameter) {
- spush(&parenliteral, CODE_ENTRY);
- dothread();
- docomma();
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(literal, compiling, "literal", doliteral);
-
- VOID doleftbracket()
- {
- state.parameter = FALSE;
- }
-
- IMMEDIATE_CODE(leftbracket, literal, "[", doleftbracket);
-
- VOID dorightbracket()
- {
- state.parameter = TRUE;
- }
-
- NORMAL_CODE(rightbracket, leftbracket, "]", dorightbracket);
-
- VOID doword()
- {
- CHAR brkchr;
-
- brkchr = (CHAR) spop(INT32);
- (VOID) io_skipspace();
- (VOID) io_scan(thetib, brkchr);
- spush(thetib, CSTR);
- }
-
- NORMAL_CODE(word_entry, rightbracket, "word", doword);
-
-
- /* VOCABULARIES */
-
- NORMAL_CONSTANT(context_entry, word_entry, "context", (INT32) context);
-
- NORMAL_CONSTANT(current_entry, context_entry, "current", (INT32) ¤t);
-
- VOID dolast()
- {
- spush((theframed ? theframed : current -> last), ENTRY);
- }
-
- NORMAL_CODE(last, current_entry, "last", dolast);
-
- VOID dodefinitions()
- {
- current = context[0];}
-
-
- NORMAL_CODE(definitions, last, "definitions", dodefinitions);
-
- VOID doonly()
- {
- INT32 v;
-
- /* Flush the entry cache */
- spush(FALSE, BOOL);
- dorestore();
-
- /* Remove all vocabularies except the first */
- for (v = 1; v < CONTEXTSIZE; v++) context[v] = NIL;
-
- /* And make it definition vocabulary */
- current = context[0];
- }
-
- NORMAL_CODE(only, definitions, "only", doonly);
-
- VOID doseal()
- {
- INT32 v;
-
- /* Flush the entry cache */
- spush(FALSE, BOOL);
- dorestore();
-
- /* Remove the first vocabulary */
- for (v = 0; context[v] = context[v + 1]; v++);
- }
-
- NORMAL_CODE(seal, only, "seal", doseal);
-
- VOID dorestore()
- {
- register INT32 i; /* Iteration variable */
- register ENTRY e; /* Pointer to parameter entry */
- register ENTRY p; /* Pointer to current entry */
-
- /* Access parameter and check if an entry */
- e = spop(ENTRY);
- if (e) {
-
- /* Flush all enties until the parameter symbol */
- for (p = current -> last; p && (p != e); p = p -> link)
- cache[hash(p -> name)] = NIL;
-
- /* If the entry was found remove all symbols until this entry */
- if (p == e) current -> last = e;
- }
- else {
-
- /* Flush the entry cache */
- for (i = 0; i < CACHESIZE; i++) cache[i] = NIL;
- }
- }
-
- NORMAL_CODE(restore, seal, "restore", dorestore);
-
- VOID dotick()
- {
- BOOL flag;
-
- spush(' ', INT32);
- doword();
- dofind();
- flag = spop(BOOL);
- if (!flag) {
- /* Print source file and line number */
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
-
- /* If not print error message and abort */
- (VOID) fprintf(io_errf, "%s ??\n", tos.CSTR);
- doabort();
- }
- }
-
- NORMAL_CODE(tick, restore, "'", dotick);
-
- VOID dobrackettick()
- {
- dotick();
- doliteral();
- }
-
- COMPILATION_IMMEDIATE_CODE(brackettick, tick, "[']", dobrackettick);
-
- VOID dolookup()
- {
- VOCABULARY_ENTRY v; /* Search vocabulary */
- register ENTRY e; /* Search entry */
- register CSTR s; /* And string */
-
- /* Fetch parameters and initate entry pointer */
- v = (VOCABULARY_ENTRY) spop(PTR32);
- s = tos.CSTR;
-
- /* Iterate over the linked list of entries */
- for (e = v -> last; e; e = e -> link)
-
- /* Compare the symbol and entry string */
- if (STREQ(s, e -> name)) {
-
- /* Check if the entry is currently visible */
- if (visible(e, v)) {
- /* Return the entry and compilation mode */
- tos.ENTRY = e;
- spush((e -> mode & IMMEDIATE ? 1 : -1), INT32);
- return;
- }
- }
- spush(FALSE, BOOL);
- }
-
- NORMAL_CODE(lookup, brackettick, "lookup", dolookup);
-
- #ifdef PROFILE
- VOID docollision()
- {
- /* Add collision statistics to profile information */
- }
- #endif
-
- VOID dofind()
- {
- ENTRY e; /* Entry in the entry cache */
- CSTR n; /* Name string of entry to be found */
- INT32 v; /* Index into vocabulary set */
-
- /* Access the string to be found */
- n = tos.CSTR;
-
- /* Check for cached entry */
- if (e = cache[hash(n)]) {
-
- /* Compare the string and the entry name */
- if (STREQ(tos.CSTR, e -> name)) {
-
- /* Check if the entry is currently visible */
- if (!(((e -> mode & COMPILATION) && (!state.parameter)) ||
- ((e -> mode & EXECUTION) && (state.parameter)))) {
- tos.ENTRY = e;
- spush((e -> mode & IMMEDIATE ? 1 : -1), INT32);
- return;
- }
- }
- #ifdef PROFILE
- else {
- docollision();
- }
- #endif
- }
-
- /* For each vocabulary in the current search chain */
- for (v = 0; context[v] && v < CONTEXTSIZE; v++) {
- spush(context[v], VOCABULARY_ENTRY);
- dolookup();
- if (tos.INT32) {
- cache[hash(n)] = snth(0).ENTRY;
- return;
- }
- else {
- sdrop();
- }
- }
- spush(FALSE, BOOL);
- }
-
- NORMAL_CODE(find, lookup, "find", dofind);
-
- VOID dorecognize()
- {
- INT32 v; /* Vocabulary index */
- ENTRY r; /* Recognizer function */
-
- for (v = 0; context[v] && v < CONTEXTSIZE; v++) {
-
- /* Check if a recognizer function is available */
- if (r = context[v] -> recognizer) {
- spush(r, ENTRY);
- docommand();
- if (tos.INT32) {
- return;
- }
- else {
- sdrop();
- }
- }
- }
-
- /* The string was not a literal symbol */
- spush(FALSE, BOOL);
- }
-
- NORMAL_CODE(recognize, find, "recognize", dorecognize);
-
- VOID doforget()
- {
- dotick();
- tos.ENTRY = tos.ENTRY -> link;
- dorestore();
- }
-
- NORMAL_CODE(forget, recognize, "forget", doforget);
-
- VOID dowords()
- {
- ENTRY e; /* Pointer to entries */
- INT32 v; /* Index into vocabulary set */
- INT32 l; /* String length */
- INT32 s; /* Spaces between words */
- INT32 c; /* Column counter */
- INT32 i; /* Loop index */
-
- /* Iterate over all vocabularies in the search set */
- for (v = 0; v < CONTEXTSIZE && context[v]; v++) {
-
- /* Print vocabulary name */
- (VOID) fprintf(io_outf, "VOCABULARY %s", context[v] -> name);
- if (context[v] == current) (VOID) fprintf(io_outf, " DEFINITIONS");
- (VOID) fputc('\n', io_outf);
-
- /* Access linked list of enties and initiate column counter */
- c = 0;
-
- /* Iterate over all entries in the vocabulary */
- for (e = context[v] -> last; e; e = e -> link) {
-
- /* Check if the entry is current visible */
- if (visible(e, context[v])) {
-
- /* Print the entry string. Check that space is available */
- l = strlen(e -> name);
- s = (c ? (COLUMNWIDTH - (c % COLUMNWIDTH)) : 0);
- c = c + s + l;
- if (c < LINEWIDTH) {
- for (i = 0; i < s; i++) (VOID) fputc(' ', io_outf);
- }
- else {
- (VOID) fputc('\n', io_outf);
- c = l;
- }
- (VOID) fprintf(io_outf, "%s", e -> name);
- }
- }
-
- /* End the list of words and separate the vocabularies */
- (VOID) fputc('\n', io_outf);
- (VOID) fputc('\n', io_outf);
- }
- }
-
- IMMEDIATE_CODE(words, forget, "words", dowords);
-
-
- /* DEFINING NEW VOCABULARY ENTRIES */
-
- ENTRY make_entry(name, code, mode, parameter)
- CSTR name; /* String for the new entry */
- INT32 code, mode, parameter; /* Entry parameters */
- {
- /* Allocate space for the entry */
- ENTRY e;
-
- /* Check type of entry to allocate */
- if (code == VOCABULARY)
- e = (ENTRY) malloc(sizeof(vocabulary_entry));
- else
- e = (ENTRY) malloc(sizeof(entry));
-
- /* Insert into the current vocabulary and set parameters */
- e -> link = current -> last;
- current -> last = e;
-
- /* Set entry parameters */
- e -> name = (CSTR) strcpy(malloc((unsigned) strlen(name) + 1), name);
- e -> code = code;
- e -> mode = mode;
- e -> parameter = parameter;
- if (code == VOCABULARY)
- ((VOCABULARY_ENTRY) e) -> recognizer = NIL;
-
- /* Check for entry caching */
- if (current == context[0])
- cache[hash(name)] = e;
- else
- cache[hash(name)] = NIL;
-
- /* Return pointer to the new entry */
- return e;
- }
-
- VOID doentry()
- {
- INT32 flag;
- CSTR name;
- INT32 code, mode, parameter;
- ENTRY forward;
-
- /* Try to find entry to check for forward declarations */
- forward = NIL;
- dodup();
- dofind();
- flag = spop(INT32);
- if (flag) {
- forward = spop(ENTRY);
- }
- else {
- sdrop();
- }
-
- /* Access name, code, mode and parameter field parameters */
- name = spop(CSTR);
- code = spop(INT32);
- mode = spop(INT32);
- parameter = spop(INT32);
-
- /* Create the new entry */
- (VOID) make_entry(name, code, mode, parameter);
-
- /* If found and forward the redirect parameter field of initial entry */
- if (forward && forward -> code == FORWARD) {
- forward -> parameter = (INT32) current -> last;
- if (verbose) {
- if (io_source())
- (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
- (VOID) fprintf(io_errf, "%s: forward definition resolved\n", forward -> name);
- }
- }
- }
-
- NORMAL_CODE(entry_entry, words, "entry", doentry);
-
- VOID doforward()
- {
- spush(0, INT32);
- spush(NORMAL, INT32);
- spush(FORWARD, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(forward, entry_entry, "forward", doforward);
-
- VOID docode()
- {
- spush(NORMAL, INT32);
- spush(CODE, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(code, forward, "code", docode);
-
- VOID docolon()
- {
- align(dp);
- dohere();
- spush(HIDDEN, INT32);
- spush(COLON, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- dorightbracket();
- thelast = current -> last;
- }
-
- NORMAL_CODE(colon, code, ":", docolon);
-
- VOID dosemicolon()
- {
- if (theframed != NIL) {
- spush(&parenunlinksemicolon, CODE_ENTRY);
- }
- else {
- spush(&parensemicolon, CODE_ENTRY);
- }
- dothread();
- doleftbracket();
- doremovelocals();
- if (thelast != NIL) {
- thelast -> mode = NORMAL;
- if (current == context[0]) cache[hash(thelast -> name)] = thelast;
- thelast = NIL;
- }
- }
-
- COMPILATION_IMMEDIATE_CODE(semicolon, colon, ";", dosemicolon);
-
- VOID docreate()
- {
- align(dp);
- dohere();
- spush(NORMAL, INT32);
- spush(CREATE, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(create, semicolon, "create", docreate);
-
- VOID dovariable()
- {
- spush(0, INT32);
- spush(NORMAL, INT32);
- spush(VARIABLE, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(variable, create, "variable", dovariable);
-
- VOID doconstant()
- {
- spush(NORMAL, INT32);
- spush(CONSTANT, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(constant, variable, "constant", doconstant);
-
- VOID dovocabulary()
- {
- spush(&forth, VOCABULARY_ENTRY);
- spush(NORMAL, INT32);
- spush(VOCABULARY, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(vocabulary, constant, "vocabulary", dovocabulary);
-
- VOID dofield()
- {
- spush(NORMAL, INT32);
- spush(FIELD, INT32);
- spush(' ', INT32);
- doword();
- doentry();
- }
-
- NORMAL_CODE(field, vocabulary, "field", dofield);
-
-
- /* INITIALIZATION OF THE KERNEL */
-
- VOID kernel_initiate(last, first, users, parameters, returns)
- ENTRY first, last;
- INT32 users, parameters, returns;
- {
- /* Link user symbols into vocabulary chain if given */
- if (first && last) {
- forth.last = last;
- first -> link = (ENTRY) &field;
- }
-
- /* Create the foreground task object */
- foreground = make_task(users, parameters, returns, (INT32) NIL);
-
- /* Assign task fields */
- foreground -> status = RUNNING;
- s0 = (PTR) foreground -> s0;
- sp = (PTR) foreground -> sp;
- r0 = foreground -> r0;
- rp = foreground -> rp;
- ip = foreground -> ip;
- fp = foreground -> fp;
- ep = foreground -> ep;
-
- /* Make the foreground task the current task */
- tp = foreground;
- }
-
- VOID kernel_finish()
- {
- /* Future clean up function for kernel */
- }
-